package com.sz.mes.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.diboot.core.entity.BaseEntity;
import com.diboot.core.util.BeanUtils;
import com.diboot.core.util.S;
import com.diboot.core.vo.JsonResult;
import com.sz.mes.entity.*;
import com.sz.mes.mapper.*;
import com.sz.mes.service.ReworkHoursService;
import com.sz.mes.service.WorkHoursService;
import com.sz.mes.util.DateUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 工时相关Service实现
 *
 * @author hem
 * @version 1.0
 * @date 2024-10-22
 * Copyright © szhs
 */
@Service
@Slf4j
@RequiredArgsConstructor
public class WorkHoursServiceImpl extends BaseCustomServiceImpl<WorkHoursMapper, WorkHours> implements WorkHoursService {

    private final ClockInMapper clockInMapper;
    private final TechniqueMapper techniqueMapper;
    private final ProductTaskMapper productTaskMapper;
    private final WorkHoursMapper workHoursMapper;
    private final ReworkHoursMapper reworkHoursMapper;
    private final ReworkClockInMapper reworkClockInMapper;
    private final ReworkTechniqueMapper reworkTechniqueMapper;

    private final ReworkHoursService reworkHoursService;


    public JsonResult test(String day) throws ParseException {

//        QueryWrapper<ClockIn> cqw = new QueryWrapper<ClockIn>()
//                .eq("operated", 0)
//                .apply("DATE(create_time) = {0}", day);
//        List<ClockIn> clockInList = clockInMapper.selectList(cqw);
//
//        List<Long> techniqueIdList = clockInList.stream().map(ClockIn::getTechniqueId).distinct().collect(Collectors.toList());
//
//        ArrayList<Technique> techniqueList = new ArrayList<>();
//        ArrayList<String> productTaskNumList = new ArrayList<>();
//        for (Long id : techniqueIdList) {
//            Technique technique = techniqueMapper.selectById(id);
//            techniqueList.add(technique);
//            productTaskNumList.add(technique.getTaskNum());
//        }
//        HashMap<Long, Long> hashMap1 = new HashMap<>();
//        for (ClockIn one : clockInList) {
//            QueryWrapper<ClockIn> qw = new QueryWrapper<ClockIn>()
//                    .eq("id", one.getPid());
//            ClockIn up = clockInMapper.selectOne(qw);
//            long ms = one.getCreateTime().getTime() - up.getCreateTime().getTime();
////            long minute = ms;
//            long minute = (ms / (60 * 1000)) % 60;
//            if (hashMap1.containsKey(up.getTechniqueId())) {
//                hashMap1.put(up.getTechniqueId(), hashMap1.get(up.getTechniqueId()) + minute);
//            } else {
//
//                hashMap1.put(up.getTechniqueId(), minute);
//            }
//        }
//        List<String> collect = productTaskNumList.stream().distinct().collect(Collectors.toList());
//        QueryWrapper<ProductTask> pqw = new QueryWrapper<ProductTask>().in("task_num", collect);
//        List<ProductTask> productTaskList1 = productTaskMapper.selectList(pqw);
//
//
//        for (ProductTask productTask : productTaskList1) {
//            List<Technique> techniques = techniqueList.stream().filter(technique -> technique.getTaskNum().equals(productTask.getTaskNum())).collect(Collectors.toList());
//            List<String> techNameList = techniques.stream().map(Technique::getTechName).distinct().collect(Collectors.toList());
//            Long allnormalTime = 0L;
//
//            for (String techName : techNameList) {
//                Long normalTime = 0L;
//
//                for (Technique one : techniques) {
//                    normalTime = hashMap1.get(one.getId());
//                    allnormalTime += normalTime;
//                }
//                WorkHours workHours = new WorkHours();
//                workHours.setReceiptNum(productTask.getReceiptNum());
//                workHours.setPlanNum(productTask.getPlanNum());
//                workHours.setTechName(techName);
//                if (techNameList.size() == 1) {
//                    workHours.setNormalTime(allnormalTime);
//                } else {
//                    workHours.setNormalTime(normalTime);
//                }
//                workHours.setWorkDay(new Date());
//                workHoursMapper.insert(workHours);
//            }
//            QueryWrapper<WorkHours> wqw = new QueryWrapper<WorkHours>().eq("receipt_num", productTask.getReceiptNum()).eq("plan_num", productTask.getPlanNum());
//            List<WorkHours> workHoursList = workHoursMapper.selectList(wqw);
//            for (WorkHours workHours1 : workHoursList) {
//                workHours1.setAllNormalTime(allnormalTime);
//                workHoursMapper.updateById(workHours1);
//            }
//        }
//
//        //返修
//        QueryWrapper<ReworkClockIn> rcqw = new QueryWrapper<ReworkClockIn>()
//                .eq("operated", 0)
//                .apply("DATE(create_time) = {0}", day);
//        List<ReworkClockIn> reworkClockIns = reworkClockInMapper.selectList(rcqw);
//
//        List<Long> techniqueIdList2 = reworkClockIns.stream().map(ReworkClockIn::getTechniqueId).distinct().collect(Collectors.toList());
//
//        ArrayList<ReworkTechnique> reworkTechniques = new ArrayList<>();
//        ArrayList<String> productTaskNumList2 = new ArrayList<>();
//        for (Long id : techniqueIdList2) {
//            ReworkTechnique reworkTechnique = reworkTechniqueMapper.selectById(id);
//            reworkTechniques.add(reworkTechnique);
//            productTaskNumList2.add(reworkTechnique.getTaskNum());
//        }
//        HashMap<Long, Long> hashMap2 = new HashMap<>();
//        for (ReworkClockIn one : reworkClockIns) {
//            QueryWrapper<ClockIn> qw = new QueryWrapper<ClockIn>()
//                    .eq("id", one.getPid());
//            ClockIn up = clockInMapper.selectOne(qw);
//            long ms = one.getCreateTime().getTime() - up.getCreateTime().getTime();
////            long minute = ms;
//            long minute = (ms / (60 * 1000)) % 60;
//            if (hashMap2.containsKey(up.getTechniqueId())) {
//                hashMap2.put(up.getTechniqueId(), hashMap2.get(up.getTechniqueId()) + minute);
//            } else {
//
//                hashMap2.put(up.getTechniqueId(), minute);
//            }
//        }
//        List<String> collect2 = productTaskNumList2.stream().distinct().collect(Collectors.toList());
//        QueryWrapper<ProductTask> qw = new QueryWrapper<ProductTask>().in("task_num", collect2);
//        List<ProductTask> productTaskList2 = productTaskMapper.selectList(qw);
//
//
//        for (ProductTask productTask : productTaskList2) {
//            List<ReworkTechnique> reworkTechniqueList = reworkTechniques.stream().filter(technique -> technique.getTaskNum().equals(productTask.getTaskNum())).collect(Collectors.toList());
//            List<String> techNameList = reworkTechniqueList.stream().map(ReworkTechnique::getTechName).distinct().collect(Collectors.toList());
////            Long allnormalTime=0L;
//            Long allreworkTime = 0L;
//            for (String techName : techNameList) {
//
////                Long normalTime=0L;
//                Long reworkTime = 0L;
//
//                for (ReworkTechnique one : reworkTechniqueList) {
//                    reworkTime = hashMap1.get(one.getId());
//                    allreworkTime += reworkTime;
//                }
//                ReworkHours reworkHours = new ReworkHours();
//                reworkHours.setReceiptNum(productTask.getReceiptNum());
//                reworkHours.setPlanNum(productTask.getPlanNum());
//                reworkHours.setTechName(techName);
//                if (techNameList.size() == 1) {
//                    reworkHours.setReworkTime(allreworkTime);
//                } else {
//                    reworkHours.setReworkTime(reworkTime);
//                }
//                reworkHours.setWorkDay(new Date());
//                reworkHoursMapper.insert(reworkHours);
//            }
//            QueryWrapper<ReworkHours> wqw = new QueryWrapper<ReworkHours>().eq("receipt_num", productTask.getReceiptNum()).eq("plan_num", productTask.getPlanNum());
//            List<ReworkHours> reworkHoursList = reworkHoursMapper.selectList(wqw);
//            for (ReworkHours workHours1 : reworkHoursList) {
//                workHours1.setAllReworkTime(allreworkTime);
//                reworkHoursMapper.updateById(workHours1);
//            }
//        }

        return JsonResult.OK();
    }

    @Override
    public void workHoursCount() throws ParseException {
        // 获取昨天下机记录
        QueryWrapper<ClockIn> cqw = new QueryWrapper<ClockIn>()
                .eq("operated", 0)
                .apply("DATE(create_time) = {0}", DateUtil.getPreDay());
        List<ClockIn> clockInList = clockInMapper.selectList(cqw);
        List<Long> collect = clockInList.stream().map(ClockIn::getPid).collect(Collectors.toList());
        if (collect.isEmpty()) {
            return;
        }
        // 对应的上机记录
        Map<Long, ClockIn> downMap = new HashMap<>();
        for (ClockIn clockIn : clockInList) {
            downMap.put(clockIn.getId(), clockIn);
        }
        cqw.clear();
        cqw.in("id", clockInList.stream().map(ClockIn::getPid).collect(Collectors.toList()));
        List<ClockIn> upClockInList = clockInMapper.selectList(cqw);
        // 上机记录
        Map<Long, ClockIn> upMap = new HashMap<>();
        for (ClockIn clockIn : upClockInList) {
            if (clockIn.getOperated() == 1) {
                upMap.put(clockIn.getId(), clockIn);
            }
        }
        // 任务工序工时
        HashMap<Long, BigDecimal> hours = new HashMap<>();
        for (Map.Entry<Long, ClockIn> entry : downMap.entrySet()) {
            ClockIn down = entry.getValue();
            ClockIn up = upMap.get(down.getPid());
            if (up == null) {
                continue;
            }
            long ms = down.getCreateTime().getTime() - up.getCreateTime().getTime();
            BigDecimal min = new BigDecimal(ms).divide(new BigDecimal(60 * 1000), 2, RoundingMode.HALF_UP);
            hours.put(down.getId(), min);
        }

        // 任务编码
        List<String> taskNumList = clockInList.stream().map(ClockIn::getTaskNum).distinct().collect(Collectors.toList());
        // 获取生产任务
        QueryWrapper<ProductTask> qw = new QueryWrapper<ProductTask>().in("task_num", taskNumList);
        List<ProductTask> productTasks = productTaskMapper.selectList(qw);
        HashMap<String, BigDecimal> totalHours = new HashMap<>();
        List<WorkHours> workHoursList = new ArrayList<>();
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        Date workDay = format.parse(DateUtil.getPreDay());
        // 记录已统计的任务
        Set<String> statistics = new HashSet<>();
        for (ProductTask productTask : productTasks) {
            // 判断是否已统计，避免重复计数
            if (statistics.contains(productTask.getTaskNum() + "-" + productTask.getReceiptNum())) {
                continue;
            }
            statistics.add(productTask.getTaskNum() + "-" + productTask.getReceiptNum());
            List<Long> keys = downMap.values().stream()
                    .filter(clockIn -> S.equals(productTask.getTaskNum(), clockIn.getTaskNum()))
                    .map(BaseEntity::getId).collect(Collectors.toList());
            BigDecimal count = BigDecimal.ZERO;
            for (Long key : keys) {
                if (!hours.containsKey(key)) {
                    continue;
                }
                WorkHours workHours = new WorkHours();
                workHours.setReceiptNum(productTask.getReceiptNum());
                workHours.setPlanNum(productTask.getPlanNum());
                workHours.setTechName(downMap.get(key).getTechName());
                workHours.setNormalTime(hours.get(key));
                workHours.setWorkDay(workDay);
                count = count.add(hours.get(key));
                workHoursList.add(workHours);
            }
            // 记录生产任务总工时
            if (totalHours.containsKey(productTask.getReceiptNum())) {
                totalHours.put(productTask.getReceiptNum(), count.add(totalHours.get(productTask.getReceiptNum())));
            } else {
                totalHours.put(productTask.getReceiptNum(), count);
            }
        }
        for (WorkHours workHours : workHoursList) {
            workHours.setAllNormalTime(totalHours.get(workHours.getReceiptNum()));
        }
        // 合并workHoursList中任务编码和工序名称相同的记录normalTime相加
        List<WorkHours> mergeList = workHoursList.stream().collect(Collectors.groupingBy(workHours -> workHours.getReceiptNum() + "-" + workHours.getTechName())).values().stream().map(value -> {
                    WorkHours merge = new WorkHours();
                    BeanUtils.copyProperties(value.get(0), merge);
                    merge.setNormalTime(value.stream().map(WorkHours::getNormalTime).reduce(BigDecimal.ZERO, BigDecimal::add));
                    return merge;
                }).collect(Collectors.toList());
        this.createEntities(mergeList);
        // 返修工时统计
        reverseRepairWorkStatistics();
    }

    /**
     * 返修工时统计
     * @throws ParseException
     */
    public void reverseRepairWorkStatistics() throws ParseException {
        // 获取昨天下机记录
        QueryWrapper<ReworkClockIn> cqw = new QueryWrapper<ReworkClockIn>()
                .eq("operated", 0)
                .apply("DATE(create_time) = {0}", DateUtil.getPreDay());
        List<ReworkClockIn> clockInList = reworkClockInMapper.selectList(cqw);
        // 对应的上机记录
        Map<Long, ReworkClockIn> downMap = new HashMap<>();
        for (ReworkClockIn clockIn : clockInList) {
            downMap.put(clockIn.getId(), clockIn);
        }
        List<Long> collect = clockInList.stream().map(ReworkClockIn::getPid).collect(Collectors.toList());
        if (collect.isEmpty()) {
            return;
        }
        cqw.clear();
        cqw.in("id", collect);
        List<ReworkClockIn> upClockInList = reworkClockInMapper.selectList(cqw);
        // 上机记录
        Map<Long, ReworkClockIn> upMap = new HashMap<>();
        for (ReworkClockIn clockIn : upClockInList) {
            if (clockIn.getOperated() == 1) {
                upMap.put(clockIn.getId(), clockIn);
            }
        }
        // 任务工序工时计算
        HashMap<Long, BigDecimal> hours = new HashMap<>();
        for (Map.Entry<Long, ReworkClockIn> entry : downMap.entrySet()) {
            ReworkClockIn down = entry.getValue();
            ReworkClockIn up = upMap.get(down.getPid());
            if (up == null) {
                continue;
            }
            long ms = down.getCreateTime().getTime() - up.getCreateTime().getTime();
            // 分钟
            BigDecimal min = new BigDecimal(ms).divide(new BigDecimal(60 * 1000), 2, RoundingMode.HALF_UP);
            hours.put(down.getId(), min);
        }

        // 任务编码
        List<String> taskNumList = clockInList.stream().map(ReworkClockIn::getTaskNum).distinct().collect(Collectors.toList());
        // 获取生产任务
        QueryWrapper<ProductTask> qw = new QueryWrapper<ProductTask>().in("task_num", taskNumList);
        List<ProductTask> productTasks = productTaskMapper.selectList(qw);
        HashMap<String, BigDecimal> totalHours = new HashMap<>();
        List<ReworkHours> workHoursList = new ArrayList<>();
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        Date workDay = format.parse(DateUtil.getPreDay());
        // 记录已统计的任务
        Set<String> statistics = new HashSet<>();
        for (ProductTask productTask : productTasks) {
            // 判断是否已统计，避免重复计数
            if (statistics.contains(productTask.getTaskNum() + "-" + productTask.getReceiptNum())) {
                continue;
            }
            statistics.add(productTask.getTaskNum() + "-" + productTask.getReceiptNum());
            List<Long> keys = downMap.values().stream()
                    .filter(clockIn -> S.equals(productTask.getTaskNum(), clockIn.getTaskNum()))
                    .map(BaseEntity::getId).collect(Collectors.toList());
            BigDecimal count = BigDecimal.ZERO;
            for (Long key : keys) {
                if (!hours.containsKey(key)) {
                    continue;
                }
                ReworkHours workHours = new ReworkHours();
                workHours.setReceiptNum(productTask.getReceiptNum());
                workHours.setPlanNum(productTask.getPlanNum());
                workHours.setTechName(downMap.get(key).getTechName());
                workHours.setReworkTime(hours.get(key));
                workHours.setWorkDay(workDay);
                count = count.add(hours.get(key));
                workHoursList.add(workHours);
            }
            // 记录生产任务总工时
            if (totalHours.containsKey(productTask.getReceiptNum())) {
                totalHours.put(productTask.getReceiptNum(), count.add(totalHours.get(productTask.getReceiptNum())));
            } else {
                totalHours.put(productTask.getReceiptNum(), count);
            }
        }
        for (ReworkHours workHours : workHoursList) {
            workHours.setAllReworkTime(totalHours.get(workHours.getReceiptNum()));
        }
        List<ReworkHours> mergeList = workHoursList.stream().collect(Collectors.groupingBy(workHours -> workHours.getReceiptNum() + "-" + workHours.getTechName())).values().stream().map(value -> {
            ReworkHours merge = new ReworkHours();
            BeanUtils.copyProperties(value.get(0), merge);
            merge.setReworkTime(value.stream().map(ReworkHours::getReworkTime).reduce(BigDecimal.ZERO, BigDecimal::add));
            return merge;
        }).collect(Collectors.toList());
        reworkHoursService.createEntities(mergeList);
    }
}
